/**
   ******************************************************************************
   * @file    main.c 
   * @author  18408107475@163.com
   * @version v1.0
   * @date    2025/03/15
   * @brief   实现通过库函数和寄存器来利用MCU的PB5、PE5控制LED0和LED1亮灭
   ******************************************************************************
**/

#include "stm32f10x.h"// 包含STM32F10x系列微控制器的头文件，该文件中定义了所有的寄存器映射和外设库函数

/**
    ******************************************************************************
    * Function name  : LED_STD_Config
    * Description    : 利用库函数对GPIO端口C的PB5、PE5口进行初始化
    * Parameter      : None
    * Return         : void
    * note           : 配置顺序:
    *							1.定义结构体变量	2.打开对应外设的时钟
    *							3.配置端口引脚模式  4.初始化
    * Modify history : None
    * version        : v1.0
    ******************************************************************************
**/
void LED_STD_Config(void)
{
    /************************************标准库配置*************************************/
    //1.定义GPIO外设的结构体变量
    // GPIO_InitTypeDef是在stm32f10x_gpio.h头文件中定义的结构体类型，用于配置GPIO引脚的相关参数
    GPIO_InitTypeDef GPIO_InitStructure;

    //2.默认复位后时钟关闭，需打开对应时钟为寄存器（触发器）提供信号；外设GPIO --> 总线APB2
    // RCC_APB2PeriphClockCmd函数用于使能或禁用APB2总线上的外设时钟
    // RCC_APB2Periph_GPIOx表示GPIOx端口的时钟，ENABLE表示使能该时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);

    //3.配置GPIO端口B的引脚5；推挽输出模式、50MHz速度
    // GPIO_Pin_5表示选择GPIOB端口的第5个引脚
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5;
    // GPIO_Speed_50MHz表示该引脚的输出速度为50MHz
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    // GPIO_Mode_Out_PP表示该引脚配置为通用推挽输出模式
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    //3.配置GPIO端口E的引脚5；推挽输出模式、50MHz速度
    // GPIO_Pin_5表示选择GPIOE端口的第5个引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

    //4.将配置好的数据传入GPIO初始化函数中
    // GPIO_Init函数用于根据GPIO_InitStructure结构体中的参数初始化指定的GPIO端口
    // GPIOC表示要初始化的端口为GPIOE，&GPIO_InitStructure表示结构体变量的地址
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    //5.默认关闭LED
    GPIO_SetBits(GPIOB,GPIO_Pin_5);
    GPIO_SetBits(GPIOE,GPIO_Pin_5);

}

/**
    ******************************************************************************
    * Function name  : LED_ST_Reg_config
    * Description    : 利用ST公司定义的寄存器对GPIO端口B和E的Pin5口进行初始化
    * Parameter      : None
    * Return         : void
    * note           : 配置顺序:
    *                   1. 打开对应外设的时钟
    *                   2. 配置端口引脚模式
    * Modify history : None
    * version        : v1.0
    ******************************************************************************
**/
void LED_ST_Reg_config(void)
{
    /************************************ST提供的寄存器配置*************************************/
    // 1. 打开对应外设的时钟
    // RCC 是指向复位和时钟控制 (RCC) 寄存器组的结构体指针
    // APB2ENR 是 RCC 寄存器组中的 APB2 外设时钟使能寄存器，用于控制 APB2 总线上外设的时钟使能
    // RCC_APB2ENR_IOPBEN 是一个宏定义，表示 APB2ENR 寄存器中使能 GPIOB 时钟的位
    // 通过按位或操作将该位置 1，开启 GPIOB 端口的时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    // RCC_APB2ENR_IOPEEN 是一个宏定义，表示 APB2ENR 寄存器中使能 GPIOE 时钟的位
    // 通过按位或操作将该位置 1，开启 GPIOE 端口的时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPEEN;

    // 2. 配置端口引脚模式
    // 对于 GPIO 端口，每个引脚的配置由 4 位控制，分别是 CNF[1:0]（配置模式位）和 MODE[1:0]（输出速度位）
    // 每个 GPIO 端口有两个 32 位的配置寄存器 CRL（用于配置引脚 0 - 7）和 CRH（用于配置引脚 8 - 15）
    // 这里要配置的是 GPIOB 和 GPIOE 的 Pin5，它们使用 CRL 寄存器

    // 配置输出速度为 50MHz
    // GPIO_CRL_MODE5_0 和 GPIO_CRL_MODE5_1 是在 stm32f10x_gpio.h 头文件中定义的宏
    // 分别对应 GPIOC_CRL 寄存器中 PB5 引脚的输出速度控制位的第 0 位和第 1 位
    // 将这两位都置 1 表示输出模式，最大速度 50MHz
    GPIOB->CRL |= (GPIO_CRL_MODE5_0 | GPIO_CRL_MODE5_1);
    // 同样地，对 GPIOE 的 Pin5 进行输出速度配置
    GPIOE->CRL |= (GPIO_CRL_MODE5_0 | GPIO_CRL_MODE5_1);

    // 配置为通用推挽输出模式
    // GPIO_CRL_CNF5 是在 stm32f10x_gpio.h 头文件中定义的宏
    // 表示 GPIOB_CRL 寄存器中 PB5 引脚的配置模式控制位
    // 通过按位与和取反操作将这些位清零，表示通用推挽输出模式
    GPIOB->CRL &= ~(GPIO_CRL_CNF5);
    // 同样地，对 GPIOE 的 Pin5 进行配置模式设置
    GPIOE->CRL &= ~(GPIO_CRL_CNF5);
}

int main()
{
    // 选择初始化方式，可以根据需要注释或取消注释下面的函数调用，选择不同的初始化方式
    //LED_STD_Config();
    LED_ST_Reg_config();
    while(1)
    {
        
        /********************************标准库操作************************************/
        /*
         * 函数库熄灭PB5/PE5-LED灯，对GPIO_Pin_5进行置位（1）操作
         * GPIO_SetBits(GPIOB,GPIO_Pin_5);
         * GPIO_SetBits(GPIOE,GPIO_Pin_5);
         * 函数库点亮PB5/PE5-LED灯，对GPIO_Pin_5进行置位（1）操作
         * GPIO_ResetBits(GPIOB,GPIO_Pin_5);
         * GPIO_ResetBits(GPIOE,GPIO_Pin_5);
         */

        /********************************寄存器操作************************************/
        /*
         * ST公司的寄存器熄灭PB/E 5-LED灯，对第5位置位（1）
         * GPIOE->BSRR |= GPIO_BSRR_BS5;
         * GPIOB->BSRR |= GPIO_BSRR_BS5;
         * 寄存器点亮PB/E 5-LED灯，对第5位复位（0）
         * GPIOB->BSRR &= ~(GPIO_BSRR_BS5);
         * GPIOE->BSRR &= ~(GPIO_BSRR_BS5);
         * GPIOC->BSRR寄存器的高16位用于置位，低16位用于复位，将第13位置1可以熄灭连接在PC13引脚上的LED灯，将第29位置1可以点亮LED灯
         */
    }

}
